package com.ebt.m.customer.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.ebt.m.R;

/**
 * created by rick.wang
 */
public class SegmentControlView extends View implements View.OnClickListener{
	
	/**
	 * 回调函数，点击按钮后触发的回调函数
	 */
	public interface OnSegmentSelectedIndexChangedListener{
    	void onSegmentChanged(int newSelectedIndex);
    }
	
	OnSegmentSelectedIndexChangedListener mOnSegmentSelectedIndexChangedListener;
	
	public void setOnSegmentSelectedIndexChangedListener(OnSegmentSelectedIndexChangedListener listener){
		mOnSegmentSelectedIndexChangedListener = listener;
	}
	
	private static final int COLOR_PRIMARY_NORMAL = 0XFFFFFFFF;
	private static final int COLOR_PRIMARY_SELECTED = 0XFF2CA99F;
	
	private static final int DEFAULT_COLOR_BACKGROUND_SELECTED = COLOR_PRIMARY_SELECTED;
	private static final int DEFAULT_COLOR_BACKGROUND_NORMAL = COLOR_PRIMARY_NORMAL;
	private static final int DEFAULT_COLOR_TEXT_SELECTED = COLOR_PRIMARY_NORMAL;
	private static final int DEFAULT_COLOR_TEXT_NORMAL = COLOR_PRIMARY_SELECTED;
	private static final int DEFAULT_COLOR_FRAME = COLOR_PRIMARY_SELECTED;
	private static final int DEFAULT_TEXT_SIZE_SP = 16;
	private static final int DEFAULT_FRAME_WIDTH_PX = 2;
	private static final int DEFAULT_FRAME_CORNER_RADIUS_PX = 0;
	private static final int DEFAULT_SELECTED_INDEX = 0;
	
    private String[] texts = null;
    
    private int colorBackgroundSelected = DEFAULT_COLOR_BACKGROUND_SELECTED;
    private int colorBackgroundNormal = DEFAULT_COLOR_BACKGROUND_NORMAL;
    private int colorTextSelected = DEFAULT_COLOR_TEXT_SELECTED;
    private int colorTextNormal = DEFAULT_COLOR_TEXT_NORMAL;
    private int colorFrame = DEFAULT_COLOR_FRAME;
    private int frameWidth = DEFAULT_FRAME_WIDTH_PX;
    private int frameCornerRadius = DEFAULT_FRAME_CORNER_RADIUS_PX;
    
    private int textSize = 0;
    private int mSelectedIndex = DEFAULT_SELECTED_INDEX;
    
    private float unitWidth = 0;
    private Paint paintText;
    private Paint paintBackground;
    private Paint paintFrame;
    
    private float textCenterYOffset;
    
    public SegmentControlView(Context context) {
        super(context);
        init();
    }
    public SegmentControlView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttr(context, attrs);
        init();
    }
    public SegmentControlView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttr(context, attrs);
        init();
    }

    private void initAttr(Context context, AttributeSet attrs) {
        if (attrs == null) {
            return;
        }

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SegmentControlView);

        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
                case R.styleable.SegmentControlView_scv_BackgroundSelectedColor:
                	colorBackgroundSelected = a.getColor(attr, DEFAULT_COLOR_BACKGROUND_SELECTED);
                    break;
                case R.styleable.SegmentControlView_scv_BackgroundNormalColor:
                	colorBackgroundNormal = a.getColor(attr, DEFAULT_COLOR_BACKGROUND_NORMAL);
                    break;
                case R.styleable.SegmentControlView_scv_TextSelectedColor:
                	colorTextSelected = a.getColor(attr, DEFAULT_COLOR_TEXT_SELECTED);
                    break;
                case R.styleable.SegmentControlView_scv_TextNormalColor:
                	colorTextNormal = a.getColor(attr, DEFAULT_COLOR_TEXT_NORMAL);
                    break;
                case R.styleable.SegmentControlView_scv_FrameColor:
                	colorFrame = a.getColor(attr, DEFAULT_COLOR_FRAME);
                    break;
                case R.styleable.SegmentControlView_scv_TextSize:
                	textSize = a.getDimensionPixelSize(attr, DEFAULT_TEXT_SIZE_SP);
                    break;
                case R.styleable.SegmentControlView_scv_TextArray:
                	texts = convertCharSequenceToString(a.getTextArray(attr));
                    break;
                case R.styleable.SegmentControlView_scv_FrameWidth:
                	frameWidth = a.getDimensionPixelSize(attr, DEFAULT_FRAME_WIDTH_PX);
                    break;
                case R.styleable.SegmentControlView_scv_FrameCornerRadius:
                	frameCornerRadius = a.getDimensionPixelSize(attr, DEFAULT_FRAME_CORNER_RADIUS_PX);
                    break;
                case R.styleable.SegmentControlView_scv_SelectedIndex:
                	mSelectedIndex = a.getInteger(attr, DEFAULT_SELECTED_INDEX);
                    break;
            }
        }
        a.recycle();
    }
    
    private RectF mRectF;
    private RectF mRectFArc;
    private Path mPathFrame;
    private void init(){
    	mRectF = new RectF();
    	mRectFArc = new RectF();
    	mPathFrame = new Path();

    	if(textSize == 0){
    		textSize = sp2px(getContext(), DEFAULT_TEXT_SIZE_SP);
    	}
    	paintText = new Paint();
    	paintText.setAntiAlias(true);
    	paintText.setTextAlign(Paint.Align.CENTER);
    	paintText.setTextSize(textSize);
        
    	paintBackground = new Paint();
    	paintBackground.setAntiAlias(true);
    	paintBackground.setStyle(Paint.Style.FILL);
        
    	paintFrame = new Paint();
    	paintFrame.setAntiAlias(true);
    	paintFrame.setStyle(Paint.Style.STROKE);
    	paintFrame.setStrokeWidth(frameWidth);
    	paintFrame.setColor(colorFrame);
    	
        textCenterYOffset = getTextCenterYOffset(paintText.getFontMetrics());
        this.setOnClickListener(this);
    }

    private float getTextCenterYOffset(Paint.FontMetrics fontMetrics){
    	if(fontMetrics == null){
    		return 0;
    	}
    	return Math.abs(fontMetrics.top + fontMetrics.bottom)/2;
    }
    
    public void setTextSize(int textSize){
    	if(this.textSize != textSize){
    		this.textSize = textSize;
    		paintText.setTextSize(textSize);
    		textCenterYOffset = getTextCenterYOffset(paintText.getFontMetrics());
    		invalidate();
    	}
    }
    
    private String[] convertCharSequenceToString(CharSequence[] csArray){
    	if(csArray == null){
    		return null;
    	}
    	String[] sArray = new String[csArray.length];
    	for(int i = 0; i < csArray.length; i++){
    		sArray[i] = csArray[i].toString();
    	}
    	return sArray;
    }
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        
        mRectF.left = getPaddingLeft();
        mRectF.top = getPaddingTop();
        mRectF.right = w - getPaddingRight();
        mRectF.bottom = h - getPaddingBottom();
        float inset = (float)Math.ceil(frameWidth / 2);
        mRectF.inset(inset, inset);

        if(texts!= null && texts.length > 0){
        	unitWidth = mRectF.width() / texts.length;
        }
        
        mRectFArc.left = 0;
		mRectFArc.top = 0;
		mRectFArc.right = 2 * frameCornerRadius;
		mRectFArc.bottom = 2 * frameCornerRadius;
    }
    
    public void setTextColor(int textColorNormal, int textColorSelected){
        this.colorTextNormal = textColorNormal;
        this.colorTextSelected = textColorSelected;
    }
    
    public void setBackgroundColor(int backgroundColorNormal, int backgroundColorSelected){
        this.colorBackgroundNormal = backgroundColorNormal;
        this.colorBackgroundSelected = backgroundColorSelected;
    }
    
    public void setFrameColor(int frameColor){
    	this.colorFrame = frameColor;
    }
    
    public void setFrameWidth(int frameWidth){
    	this.frameWidth = frameWidth;
    }
    
    public void setTexts(String[] texts){
    	if(texts == null || texts.length < 2){
    		throw new IllegalArgumentException("SegmentControlView's content text array'length should larger than 1");
    	}
    	this.texts = texts;
       	unitWidth = mRectF.width() / texts.length;
    }
    
    public void update(){
    	invalidate();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(!isStringArrayEmpty(texts)){
        	drawBackgroundAndFrameAndText(canvas);
        }
    }
    
    public void setSelectedIndex(int selectedIndex){
    	if(mSelectedIndex != selectedIndex){
    		mSelectedIndex = selectedIndex;
    		if(mOnSegmentSelectedIndexChangedListener != null){
    			mOnSegmentSelectedIndexChangedListener.onSegmentChanged(mSelectedIndex);
    		}
    		invalidate();
    	}
    }
    private void drawBackgroundAndFrameAndText(Canvas canvas){
    	for(int i = 0; i < texts.length; i++){
    		float left = mRectF.left + unitWidth * i;
    		mPathFrame.reset();
    		if(i == 0){
    			mPathFrame.moveTo(mRectF.left, mRectF.top + frameCornerRadius);
    			mRectFArc.offsetTo(mRectF.left, mRectF.top);
    			mPathFrame.arcTo(mRectFArc, 180, 90);
    			mPathFrame.lineTo(mRectF.left + unitWidth, mRectF.top);
    			mPathFrame.lineTo(mRectF.left + unitWidth, mRectF.bottom);
    			mPathFrame.lineTo(mRectF.left + frameCornerRadius, mRectF.bottom);
    			mRectFArc.offsetTo(mRectF.left, mRectF.bottom - 2 * frameCornerRadius);
    			mPathFrame.arcTo(mRectFArc, 90, 90);
    		}else if(i == (texts.length - 1)){
    			mPathFrame.moveTo(mRectF.left + i * unitWidth, mRectF.top);
    			mPathFrame.lineTo(mRectF.right - frameCornerRadius, mRectF.top);
    			mRectFArc.offsetTo(mRectF.right - 2 * frameCornerRadius, mRectF.top);
    			mPathFrame.arcTo(mRectFArc, 270, 90);
    			mPathFrame.lineTo(mRectF.right, mRectF.bottom - frameCornerRadius);
    			mRectFArc.offsetTo(mRectF.right - 2 * frameCornerRadius, mRectF.bottom - 2 * frameCornerRadius);
    			mPathFrame.arcTo(mRectFArc, 0, 90);
    			mPathFrame.lineTo(mRectF.left + i * unitWidth, mRectF.bottom);
    		}else{
    			mPathFrame.moveTo(left, mRectF.top);
    			mPathFrame.lineTo(left + unitWidth, mRectF.top);
    			mPathFrame.lineTo(left + unitWidth, mRectF.bottom);
    			mPathFrame.lineTo(left, mRectF.bottom);
    		}
    		mPathFrame.close();
			paintBackground.setColor(i == mSelectedIndex ? colorBackgroundSelected : colorBackgroundNormal);
			if(curTouchedIndex == i){
				paintBackground.setColor(getDarkColor(paintBackground.getColor(), TOUCHED_BACKGROUND_DARK_COEFFICIENT));
			}
			canvas.drawPath(mPathFrame, paintBackground);
			canvas.drawPath(mPathFrame, paintFrame);
    		
    		paintText.setColor(i == mSelectedIndex ? colorTextSelected : colorTextNormal);
    		canvas.drawText(texts[i], left + unitWidth / 2,mRectF.centerY() + textCenterYOffset, paintText);
    	}
    }
    
    private int getTouchedIndex(float x, float y){
    	
    	if(!mRectF.contains(x, y)){
    		return -1;
    	}
    	for(int i = 0; i < texts.length; i++){
    		if(mRectF.left + i * unitWidth <= x && x < mRectF.left + (i + 1) * unitWidth){
    			return i;
    		}
    	}
    	return -1;
    }
    
    int preTouchedIndex = -1;
    int curTouchedIndex = -1;
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		preTouchedIndex = curTouchedIndex;
		switch(event.getAction()){
		case MotionEvent.ACTION_DOWN:
			curTouchedIndex = getTouchedIndex(event.getX(), event.getY());
			if(preTouchedIndex != curTouchedIndex){
				invalidate();
			}
			break;
		case MotionEvent.ACTION_MOVE:
			curTouchedIndex = getTouchedIndex(event.getX(), event.getY());
			if(preTouchedIndex != curTouchedIndex){
				invalidate();
			}
			break;
		case MotionEvent.ACTION_UP:
			curTouchedIndex = getTouchedIndex(event.getX(), event.getY());
			if(curTouchedIndex != -1){
				if(mOnSegmentSelectedIndexChangedListener != null && mSelectedIndex != curTouchedIndex){
					mOnSegmentSelectedIndexChangedListener.onSegmentChanged(curTouchedIndex);
				}
				mSelectedIndex = curTouchedIndex;
			}
			curTouchedIndex = -1;
			invalidate();
			break;
		case MotionEvent.ACTION_CANCEL:
			curTouchedIndex = -1;
			invalidate();
			break;
		}
		return super.onTouchEvent(event);
	}
    
    @Override
	public void onClick(View v) {
    }

    //THANKS TO SlidingTabLayout
    private ViewPager mViewPager;
    public void setViewPager(ViewPager viewPager) {
        mViewPager = viewPager;
        if (viewPager != null) {
            viewPager.setOnPageChangeListener(new InternalViewPagerListener());
        }
    }
    
    private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
        private int mScrollState;

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        	mScrollState = state;
        }

        @Override
        public void onPageSelected(int position) {
        	SegmentControlView.this.setSelectedIndex(position);
        }
    }

    private static final float TOUCHED_BACKGROUND_DARK_COEFFICIENT = 0.95F;
    public static int getDarkColor(int color, float darkCoefficient){
    	
    	int a = (color & 0xff000000) >>> 24;
    	int r = (color & 0x00ff0000) >>> 16;
    	int g = (color & 0x0000ff00) >>> 8;
    	int b = (color & 0x000000ff) >>> 0;
    	
    	r = (int)(r * darkCoefficient);
    	g = (int)(g * darkCoefficient);
    	b = (int)(b * darkCoefficient);
    	
    	return a << 24 | r << 16 | g << 8 | b;
    }
   
    private boolean isStringArrayEmpty(String[] array){
    	return (array == null || array.length == 0);
    }
    
    public static int sp2px(Context context, float spValue) {  
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;  
        return (int) (spValue * fontScale + 0.5f);  
    } 
}